"""
Created on 17-Aug-2009

@author: dexen
"""

import time

from multiprocessing.managers import BaseManager
from dexen.system.common.states import MasterState, TaskState
from dexen.system.common.transact import (SlaveTransact, MasterRecvTransact,
                                          Transaction, RecvTransact)

class MyManager(BaseManager):
    pass

class Action(object):
    def __init__(self, seq_no, master_state, transact):
        self.id = seq_no
        self.master_state = master_state
        self.transact = transact
        self.creation_time = time.strftime("%b%d-%a-%H:%M:%S", time.localtime())
    
    def get_id(self):
        return self.id
    
    def get_transact(self):
        return self.transact
    
    def get_master_state(self):
        return self.master_state
    
    def is_slave(self):
        return isinstance(self.transact, SlaveTransact)
    
    def is_receive(self):
        return isinstance(self.transact, RecvTransact)
    
    def is_master(self):
        return isinstance(self.transact, MasterRecvTransact)
    
    def get_inds(self):
        transact = self.transact
        assert isinstance(transact, Transaction)
        return transact.get_inds()

    def _get_task_headers(self):
        master_state = self.master_state
        assert isinstance(master_state, MasterState)
        task_states = master_state.get_task_states()
        header = ""
        for task_state in task_states:
            assert isinstance(task_state, TaskState)
            header += ",%s"%(TaskState.get_header())
        return header

    def get_header_(self):
        header = "ActId,TransId,Task,Outcome,StartTime,AvgTime,ExecTime"
        return header + self._get_task_headers()
    
    def get_header(self):
        header = "ActId,%s,StartTime"%(Transaction.get_header())
        header += self._get_task_headers()
        return header
            
    def get_log(self):
        log = ""
        transact = self.transact
        assert isinstance(transact, Transaction)
        log += "%s,%s,%s"%(self.id, transact.get_log(), self.creation_time)
        master_state = self.master_state
        assert isinstance(master_state, MasterState)
        for task_state in master_state.get_task_states():
            log += ",  ,%s"%(task_state.get_log())
        return log
    
    def __repr__(self):
        out = "%s\n"%("".center(40,'='))
        out += "ActId: %s\n"%(self.id)
        out += self.transact.__repr__()
        #out += "%s\n"%("".center(40,'+'))
        return out

#===============================================================================
# Task Base Classes
#===============================================================================
class BaseSlaveTask(object):
    def __initialize__(self):
        pass
    
    def __execute__(self, master_state, inds=[]):
        pass
    
class BaseMasterTask(object):
    def __execute__(self, master_env):
        pass 


#===============================================================================
# Individual Base Class
#===============================================================================
import types


def _is_simple(obj):
    res = type(obj) == types.FloatType
    res = res or type(obj) == types.IntType
    res = res or type(obj) == types.BooleanType
    res = res or type(obj) == types.LongType
    return  res
        

class Individual(object):
    def __init__(self):
        self.__archived__ = {}
        self.__modified__ = {}
        self._act_time = None # refers to the action id
        self._inact_time = None # refers to the action id
    
    def _reset_modified(self):
        self.__modified__ = {}
          
    def __setattr__(self, name, value):
        if name == "__modified__":
            object.__setattr__(self, name, value)
            return
        if not hasattr(self, "__modified__"):
            self.__modified__ = {}
        self.__modified__[name] = value
        object.__setattr__(self, name, value)
    
    def _set_act_time(self, seq_no):
        self._act_time = seq_no
    
    def _get_act_time(self):
        return self._act_time
    
    def _set_inact_time(self, seq_no):
        self._inact_time = seq_no
    
    def _get_inact_time(self):
        return self._inact_time
    
    def _set_id(self, id):
        self.__id__ = id
    
    def _get_id(self):
        if self._is_new():
            return None
        return self.__id__
    
    def _is_new(self):
        return not hasattr(self, "__id__")
    
    def archive_data(self, name, content):
        self.__archived__[name] = str(content)
    
    def _strip_archived(self):
        self.__archived__ = {}

    def _get_archived(self):
        return self.__archived__    
    
    def __stripped_clone__(self):
        ind = Individual()
        ind.__id__ = self._get_id()
        for name in dir(self):
            obj = getattr(self, name)
            if _is_simple(obj):
                setattr(ind, name, obj)
        ind._act_time = self._act_time
        ind._inact_time = self._inact_time
        ind.__archived__ = self.__archived__
        return ind
    
    @classmethod  
    def _get_header(self):
        out = "Id,ActTime,InActTime"
        return out    
    
    def _get_pareto_log(self):
        out = "%s,%s,%s"%(self.__id__, self._act_time, self._inact_time)
        return out
    
    def __repr__(self):
        out = "------------ Individual -----------\n"
        out += "Id: %s\n"%(self._get_id())
        out += "-----------------------------------\n"
        return out

#===============================================================================
# TESTING
#===============================================================================
import cPickle

class A(object):
    def __init__(self):
        self.k = 5

def test():
    ind = Individual()
    ind.a = "haha"
    ind.b = [1,2,4,5]
    ind.c = A()
    ind.d = 3
    ind.e = 3.5
    print ind.__modified__.keys()
    ind.__modified__ = {}
    raw = cPickle.dumps(ind)
    ind = cPickle.loads(raw)
    print ind.__modified__.keys()
    print len(dir(ind)), dir(ind)
    ind = ind.__stripped_clone__()
    print len(dir(ind)), dir(ind)
    
def test2():
    ind = Individual()
    ind.haha = 4
    #ind.set_score("haha", "da", score.MINIMIZE)
    ind.veli = 5
    ind.__id__ = 3
    ind.archive_data("ali.txt", "Korkma sonmez bu safa")
    ind.archive_data("veli ka.txt", range(20))
    print ind.get_archived_data()
    ind.strip_archived()
    print ind.get_archived_data()
    ind.strip_all()
    print ind.__dict__
    
def main():
    test()    
    #test2()
    
if __name__ == "__main__":
    main()



